package com.dge.common.widgets.view;

import android.animation.ObjectAnimator;
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;

import com.blankj.utilcode.util.BarUtils;
import com.dge.common.utils.SizeConvertUtils;
import com.dge.widget.view.DrawableTextView;

import timber.log.Timber;

/**
 * 可拖动的fab按钮，继承了DrawableTextView的特性
 */
public class DragFloatActionButton extends DrawableTextView {
    private static final String TAG = "DragFloatActionButton";
    private int parentHeight;
    private int parentWidth;
    Handler handler = new Handler();
    int touchSlop = 0;
    boolean isFirstMove = false;
    long downTimeMills = 0;
    long upTimeMills = 0;
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            setAlpha(0.3f);
        }
    };

    private int lastX;
    private int lastY;
    private final int edgeMargin = SizeConvertUtils.INSTANCE.dp2px(16); //左右边距
    private final int statusBarHeight = BarUtils.getStatusBarHeight(); //上边距
    private boolean isDrag;
    private ViewGroup parent;

    public DragFloatActionButton(Context context) {
        super(context);
        touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    }

    public DragFloatActionButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    }

    public DragFloatActionButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int rawX = (int) event.getRawX();
        int rawY = (int) event.getRawY();
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                this.setAlpha(0.9f);
                setPressed(true);
                isDrag = false;
                getParent().requestDisallowInterceptTouchEvent(true);
                lastX = rawX;
                lastY = rawY;
                if (getParent() != null) {
                    parent = (ViewGroup) getParent();
                    Timber.d("parent = %s", parent);
                    parentHeight = parent.getHeight();
                    parentWidth = parent.getWidth();
                }
                Timber.d("parentHeight = " + parentHeight + "; parentWidth = " + parentWidth);
                downTimeMills = System.currentTimeMillis();
                isFirstMove = true;
                break;
            case MotionEvent.ACTION_MOVE:
                if (parentHeight <= 0.2 || parentWidth <= 0.2) {
                    isDrag = false;
                    break;
                } else {
                    isDrag = true;
                }
                this.setAlpha(0.9f);
                int dx = rawX - lastX;
                int dy = rawY - lastY;
                //这里修复一些华为手机无法触发点击事件
                int distance = (int) Math.sqrt(dx * dx + dy * dy);
                Timber.d("touchSlop = " + touchSlop + ";isFirstMove = " + isFirstMove + "; distance = " + distance + "; getWidth() = " + getWidth());
                if ((isFirstMove && distance < getWidth()) || (!isFirstMove && distance < touchSlop && System.currentTimeMillis() - downTimeMills < 500)) {
                    isDrag = false;
                    isFirstMove = false;
                    break;
                }
                float x = getX() + dx;
                float y = getY() + dy;
                int rightEdge = parentWidth - getWidth() - edgeMargin;
                int height = getHeight();
                //检测是否到达边缘 左上右下
                x = x < edgeMargin ? edgeMargin : x > rightEdge ? rightEdge : x;
                y = y < statusBarHeight ? statusBarHeight : y + height > parentHeight ? parentHeight - height : y;
                setX(x);
                setY(y);
                lastX = rawX;
                lastY = rawY;
                Timber.i("isDrag = %s; getX = %s; getY = %s; parentWidth = %s", isDrag, getX(), getY(), parentWidth);
                isFirstMove = false;
                break;
            case MotionEvent.ACTION_UP:
                isFirstMove = false;
                if (!isNotDrag()) {
                    //恢复按压效果
                    setPressed(false);
                    moveHide(rawX);
                } else {
                    myRunable();
                }
                upTimeMills = System.currentTimeMillis();
                break;
        }
        if (upTimeMills - downTimeMills > 500) { //按下时间大于500ms则消耗事件，不响应点击事件
            return true;
        } else {
            //如果是拖拽则消耗事件，否则正常传递即可。
            return !isNotDrag() || super.onTouchEvent(event);
        }
    }

    private boolean isNotDrag() {
        return !isDrag && (getX() <= edgeMargin || getX() >= parentWidth - getWidth() - edgeMargin
                || getY() < statusBarHeight || getY() + getHeight() > parentHeight);
    }

    private void moveHide(int rawX) {
        if (rawX >= parentWidth / 2) {
            //靠右吸附
            animate().setInterpolator(new DecelerateInterpolator())
                    .setDuration(500)
                    .xBy(parentWidth - getWidth() - getX() - edgeMargin)
                    .start();
            myRunable();
        } else {
            //靠左吸附
            ObjectAnimator oa = ObjectAnimator.ofFloat(this, "x", getX(), edgeMargin);
            oa.setInterpolator(new DecelerateInterpolator());
            oa.setDuration(500);
            oa.start();
            myRunable();
        }
    }

    private void myRunable() {
        // 不增加透明度
        // handler.removeCallbacks(runnable);
        // handler.postDelayed(runnable, 2000);
    }
}
